<template>
  <div class="dashboard-container">
    <div class="top-section">
      <div class="left-charts">
        <div class="chart-card">
          <h3 class="card-title">近24小时缺陷趋势</h3>
          <div class="chart" ref="dailyTrendChart"></div>
        </div>
        <div class="chart-card">
          <h3 class="card-title">近30天缺陷趋势</h3>
          <div class="chart" ref="monthlyTrendChart"></div>
        </div>
      </div>
      <div class="right-chart">
        <div class="chart-card">
          <h3 class="card-title">缺陷类型分布</h3>
          <div class="chart" ref="typeDistributionChart"></div>
        </div>
      </div>
    </div>
    <div class="bottom-section">
      <div class="table-card">
        <h3 class="card-title">实时新增缺陷列表</h3>
        <div class="table-container">
          <div class="table-header">
            <div class="col col-1">ID</div>
            <div class="col col-2">缺陷名称</div>
            <div class="col col-3">描述</div>
            <div class="col col-4">严重等级</div>
            <div class="col col-5">时间</div>
          </div>
          <transition-group name="list" tag="div" class="table-body">
            <div v-for="item in defects" :key="item.id" class="table-row">
              <div class="col col-1">{{ item.id }}</div>
              <div class="col col-2">{{ item.flawName }}</div>
              <div class="col col-3">{{ item.flawDesc }}</div>
              <div class="col col-4">
                <span class="severity" :style="{ backgroundColor: getSeverityColor(item.flawType) }">{{ item.flawType }}</span>
              </div>
              <div class="col col-5">{{ formatTime(item.createTime) }}</div>
            </div>
          </transition-group>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import { listFlaw } from '@/axios/api';
import type { AgvFlaw } from '@/axios/types';
import { ElMessage } from 'element-plus';

// Get the type from the return value of the init function
type EChartsInstance = ReturnType<typeof echarts.init>;

// --- Refs for chart elements ---
const dailyTrendChart = ref<HTMLElement | null>(null);
const monthlyTrendChart = ref<HTMLElement | null>(null);
const typeDistributionChart = ref<HTMLElement | null>(null);

// --- Chart Instances ---
let dailyChartInstance: EChartsInstance | null = null;
let monthlyChartInstance: EChartsInstance | null = null;
let typeChartInstance: EChartsInstance | null = null;

// --- ECharts Options ---
const getBaseChartOptions = () => ({
  grid: { top: '20%', right: '5%', bottom: '15%', left: '10%' },
  tooltip: { trigger: 'axis', backgroundColor: '#1B263B', borderColor: '#36A2EB', textStyle: { color: '#E0E0E0' } },
  xAxis: {
    axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } },
    axisLabel: { color: '#E0E0E0' },
  },
  yAxis: {
    axisLine: { lineStyle: { color: 'rgba(255, 255, 255, 0.3)' } },
    axisLabel: { color: '#E0E0E0' },
    splitLine: { lineStyle: { type: 'dashed', color: 'rgba(255, 255, 255, 0.1)' } },
  },
});

const dailyTrendOptions = {
  ...getBaseChartOptions(),
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: Array.from({ length: 24 }, (_, i) => `${String(i).padStart(2, '0')}:00`),
  },
  yAxis: { ...getBaseChartOptions().yAxis, name: '新增缺陷数' },
  series: [{
    name: '缺陷数',
    type: 'line',
    smooth: true,
    symbol: 'emptyCircle',
    symbolSize: 8,
    itemStyle: { color: '#36A2EB' },
    lineStyle: { width: 3 },
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        { offset: 0, color: 'rgba(54, 162, 235, 0.5)' },
        { offset: 1, color: 'rgba(54, 162, 235, 0)' }
      ])
    },
    data: [], // Populated from API
  }]
};

const monthlyTrendOptions = {
  ...getBaseChartOptions(),
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: Array.from({ length: 30 }, (_, i) => `Day ${i + 1}`),
  },
  yAxis: { ...getBaseChartOptions().yAxis, name: '新增缺陷数' },
  series: [{
    name: '缺陷数',
    type: 'line',
    smooth: true,
    symbol: 'none',
    itemStyle: { color: '#4BC0C0' },
    lineStyle: { width: 3 },
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        { offset: 0, color: 'rgba(75, 192, 192, 0.5)' },
        { offset: 1, color: 'rgba(75, 192, 192, 0)' }
      ])
    },
    data: [], // Populated from API
  }]
};

const typeDistributionOptions = {
  ...getBaseChartOptions(),
  grid: { top: '10%', right: '10%', bottom: '5%', left: '25%' },
  tooltip: { ...getBaseChartOptions().tooltip, trigger: 'item' },
  xAxis: { type: 'value', splitLine: { show: false } },
  yAxis: {
    type: 'category',
    data: [], // Populated from API
    axisTick: { show: false },
  },
  series: [{
    name: '缺陷数量',
    type: 'bar',
    barWidth: '60%',
    itemStyle: {
      borderRadius: [0, 4, 4, 0],
      color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
        { offset: 0, color: 'rgba(153, 102, 255, 1)' }, // #9966FF
        { offset: 1, color: 'rgba(153, 102, 255, 0.4)' }
      ])
    },
    label: { show: true, position: 'right', color: '#fff' },
    data: [], // Populated from API
  }],
};
(typeDistributionOptions.yAxis.data as string[]).reverse();
(typeDistributionOptions.series[0].data as number[]).sort((a,b) => a - b);


// --- Real-time Table Data ---
const defects = ref<AgvFlaw[]>([]);
let intervalId: number | undefined;

const severityColors = ['#FF6384', '#FF9F40', '#36A2EB', '#4BC0C0', '#9966FF', '#FFCD56'];
const getSeverityColor = (type?: string): string => {
  if (!type) return '#6c757d'; // Default gray color for unknown types
  // Simple hash function to get a consistent color index for any string
  let hash = 0;
  for (let i = 0; i < type.length; i++) {
    hash = type.charCodeAt(i) + ((hash << 5) - hash);
    hash = hash & hash; // Convert to 32bit integer
  }
  const index = Math.abs(hash % severityColors.length);
  return severityColors[index];
};

// --- Date & Time Helpers ---
const parseDate = (dateString?: string): Date | null => {
  if (!dateString) return null;
  // Replace space with 'T' for ISO 8601 compatibility, which is robustly handled by new Date()
  return new Date(dateString.replace(' ', 'T'));
};

const formatTime = (timeStr?: string) => {
  if (!timeStr) return 'N/A';
  const date = parseDate(timeStr);
  // Use 'sv-SE' locale to get a 'YYYY-MM-DD HH:mm:ss' format easily
  return date ? date.toLocaleString('sv-SE') : 'Invalid Date';
};

// --- Data Loading and Processing ---

const loadAndProcessData = async () => {
  try {
    // Fetch ALL flaws to ensure trend analysis is accurate
    const res = await listFlaw({ pageNum: 1, pageSize: 999 });
    if (res.code === 200) {
      const allFlaws = res.rows as AgvFlaw[];

      // Process for charts
      updateDailyTrendChart(allFlaws);
      updateMonthlyTrendChart(allFlaws);
      updateTypeDistributionChart(allFlaws);

      // Initial table population
      updateTable(allFlaws);

    } else {
      ElMessage.error('获取缺陷数据失败: ' + res.msg);
    }
  } catch (error) {
    console.error('API Error:', error);
    ElMessage.error('请求缺陷数据时发生网络错误');
  }
};

const pollForNewDefects = async () => {
  try {
    // Add sorting parameters to fetch the LATEST defects
    const res = await listFlaw({ 
      pageNum: 1, 
      pageSize: 8,
      orderByColumn: 'createTime',
      isAsc: 'desc'
    });
    if (res.code === 200) {
      updateTable(res.rows as AgvFlaw[]);
    }
  } catch(e) {
    console.error("Polling error:", e)
  }
}

const updateTable = (newFlaws: AgvFlaw[]) => {
    // Sort by creation time descending to get the latest
    const latestFlaws = newFlaws.sort((a, b) => new Date(b.createTime!).getTime() - new Date(a.createTime!).getTime());
    
    // Naive update: just replace with the latest 8.
    // For a more robust solution, we would compare IDs.
    defects.value = latestFlaws.slice(0, 8);
}


const updateDailyTrendChart = (flaws: AgvFlaw[]) => {
    const now = new Date();
    const hourlyCounts = new Array(24).fill(0);
    const hourLabels = Array.from({length: 24}, (_, i) => {
        const h = (now.getHours() - (23 - i) + 24) % 24;
        return `${String(h).padStart(2, '0')}:00`;
    });

    const twentyFourHoursAgo = new Date();
    twentyFourHoursAgo.setHours(twentyFourHoursAgo.getHours() - 23);
    twentyFourHoursAgo.setMinutes(0);
    twentyFourHoursAgo.setSeconds(0);
    
    flaws.forEach(flaw => {
        const flawDate = parseDate(flaw.createTime);
        if (flawDate && flawDate.getTime() >= twentyFourHoursAgo.getTime()) {
            const hoursDiff = Math.floor((flawDate.getTime() - twentyFourHoursAgo.getTime()) / (1000 * 60 * 60));
            if (hoursDiff >= 0 && hoursDiff < 24) {
                hourlyCounts[hoursDiff]++;
            }
        }
    });

    dailyTrendOptions.xAxis.data = hourLabels as any;
    dailyTrendOptions.series[0].data = hourlyCounts as any;
    dailyChartInstance?.setOption(dailyTrendOptions);
};

const updateMonthlyTrendChart = (flaws: AgvFlaw[]) => {
    const dailyCounts = new Array(30).fill(0);
    const days = Array.from({length: 30}, (_, i) => {
        const d = new Date();
        d.setDate(d.getDate() - i);
        return d.toISOString().split('T')[0];
    }).reverse();

    const thirtyDaysAgo = new Date(days[0]);

    flaws.forEach(flaw => {
        const flawDate = parseDate(flaw.createTime);
        if (flawDate && flawDate.getTime() >= thirtyDaysAgo.getTime()) {
            const flawDateString = flawDate.toISOString().split('T')[0];
            const index = days.indexOf(flawDateString);
            if (index > -1) {
                dailyCounts[index]++;
            }
        }
    });

    monthlyTrendOptions.xAxis.data = days.map(d => d.substring(5)); // M-D format
    monthlyTrendOptions.series[0].data = dailyCounts as any;
    monthlyChartInstance?.setOption(monthlyTrendOptions);
};

const updateTypeDistributionChart = (flaws: AgvFlaw[]) => {
  const typeCounts: { [key: string]: number } = {};
  flaws.forEach(flaw => {
    const type = flaw.flawType || '未知类型';
    typeCounts[type] = (typeCounts[type] || 0) + 1;
  });

  const sortedTypes = Object.entries(typeCounts).sort((a, b) => a[1] - b[1]);

  typeDistributionOptions.yAxis.data = sortedTypes.map(entry => entry[0]) as any;
  typeDistributionOptions.series[0].data = sortedTypes.map(entry => entry[1]) as any;
  typeChartInstance?.setOption(typeDistributionOptions);
};

// --- Lifecycle Hooks ---
onMounted(() => {
  // Init charts
  nextTick(() => {
    dailyChartInstance = echarts.init(dailyTrendChart.value!);
    monthlyChartInstance = echarts.init(monthlyTrendChart.value!);
    typeChartInstance = echarts.init(typeDistributionChart.value!);

    // Load initial data and populate charts & table
    loadAndProcessData();
  });

  // Start polling for real-time updates
  intervalId = window.setInterval(pollForNewDefects, 5000);
  
  // Resize listener
  window.addEventListener('resize', resizeCharts);
});

onUnmounted(() => {
  clearInterval(intervalId);
  window.removeEventListener('resize', resizeCharts);
  dailyChartInstance?.dispose();
  monthlyChartInstance?.dispose();
  typeChartInstance?.dispose();
});

const resizeCharts = () => {
  dailyChartInstance?.resize();
  monthlyChartInstance?.resize();
  typeChartInstance?.resize();
};

</script>

<style scoped>
/* --- Base Layout & Colors --- */
.dashboard-container {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background-color: #0D1B2A; /* Midnight Blue */
  color: #E0E0E0;
  font-family: 'Inter', 'Noto Sans SC', 'Microsoft YaHei', sans-serif;
  display: flex;
  flex-direction: column;
  padding: 20px;
  box-sizing: border-box;
  overflow: hidden; /* Prevent scrolling */
}

/* --- Sections --- */
.top-section {
  height: 60%;
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
}

.bottom-section {
  height: 40%;
  display: flex;
}

/* --- Chart Layout --- */
.left-charts {
  flex: 3;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.right-chart {
  flex: 2;
  display: flex;
}

/* --- Card Styling --- */
.chart-card,
.table-card {
  background-color: #1B263B; /* Deep Slate Blue */
  border-radius: 8px;
  padding: 16px;
  box-shadow: inset 0 0 15px rgba(54, 162, 235, 0.1), 0 0 5px rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(54, 162, 235, 0.2);
  display: flex;
  flex-direction: column;
  width: 100%;
}

.left-charts .chart-card {
  flex: 1;
}

.card-title {
  margin: 0 0 10px 0;
  font-size: 18px;
  font-weight: 500;
  color: #FFFFFF;
  border-left: 4px solid #36A2EB;
  padding-left: 10px;
}

.chart {
  width: 100%;
  height: 100%;
  flex-grow: 1;
}

/* --- Table Styling --- */
.table-card {
  width: 100%;
}

.table-container {
  flex-grow: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.table-header, .table-row {
  display: flex;
  width: 100%;
  padding: 10px 12px;
  box-sizing: border-box;
}

.table-header {
  font-weight: bold;
  color: #90b8de;
  border-bottom: 1px solid rgba(54, 162, 235, 0.3);
}

.table-body {
  flex-grow: 1;
}

.table-row {
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  transition: all 0.5s ease-in-out;
}
.table-body .table-row:nth-child(odd) {
  background-color: rgba(255, 255, 255, 0.02);
}

.col { 
  text-align: left;
  padding: 0 5px; /* Add some padding */
  white-space: nowrap; /* Prevent wrapping by default */
  overflow: hidden;
  text-overflow: ellipsis; /* Add ellipsis for overflow */
}
.col-1 { flex: 0 0 8%; }
.col-2 { flex: 1 1 20%; }
.col-3 { 
  flex: 1 1 30%; 
  white-space: pre-wrap; /* Allow wrapping for description */
  word-break: break-all;
}
.col-4 { flex: 0 0 15%; text-align: center; }
.col-5 { flex: 0 0 27%; text-align: right; }

.severity {
  padding: 4px 12px;
  border-radius: 4px;
  color: #fff;
  font-weight: bold;
}
.severity-high { background-color: #FF6384; }
.severity-medium { background-color: #FF9F40; } /* Orange */
.severity-low { background-color: #36A2EB; }

/* --- Table Animation --- */
.list-enter-active {
  transition: all 0.8s cubic-bezier(0.55, 0, 0.1, 1);
}
.list-leave-active {
  transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
  position: absolute; /* Important for smooth leave animation */
}

.list-enter-from {
  opacity: 0;
  transform: translateY(-40px) scale(1.05);
  background-color: rgba(54, 162, 235, 0.3);
}
.list-leave-to {
  opacity: 0;
  transform: translateY(30px) scale(0.95);
}
</style>
